package com.mayi.crm.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mayi.crm.base.BaseService;
import com.mayi.crm.dao.UserMapper;
import com.mayi.crm.dao.UserRoleMapper;
import com.mayi.crm.model.UserRole;
import com.mayi.crm.query.UserQuery;
import com.mayi.crm.utils.*;
import com.mayi.crm.model.User;
import com.mayi.crm.vo.UserVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author yacong_liu
 * @version 1.0
 * @classname UserService
 * @description 用户业务层
 * @date 2021/1/13
 **/
@Service
public class UserService extends BaseService<User, Integer> {

    @Autowired
    private UserMapper userMapper;

    @Resource
    private UserRoleMapper userRoleMapper;

    /**
     * @param userName 用户名
     * @param passWord 密码
     * @return void
     * @description 用户登录
     * @date 2021/1/13 16:19
     **/
    public UserVo userLogin(String userName, String passWord) {
        // 1. 参数校验
        checkLoginParams(userName, passWord);

        // 2. 通过用户名查询用户记录
        User user = userMapper.queryUserByName(userName);

        // 3. 判断用户对象是否为空
        AssertUtil.isTrue(null == user, "用户不存在！");

        // 4. 判断密码是否一致。比对客户端传输的密码与数据库中存储的密码是否一致
        checkPassWord(passWord, user.getUserPwd());

        // 5. 用户登录成功，返回用户相关信息
        return buildUserInfo(user);
    }

    /**
     * @param [userId, newPassWord, oldPassWord, confirmPassWord]
     * @return void
     * @description 更新密码
     * @date 2021/1/15 13:39
     **/
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateUserPassWord(Integer userId, String newPassWord, String oldPassWord, String confirmPassWord) {

        // 1. 通过userId获取用户对象
        User user = userMapper.selectByPrimaryKey(userId);
        // 2. 参数校验
        checkUpdatePassWordParams(user, newPassWord, oldPassWord, confirmPassWord);
        // 3. 设置用户新密码 新密码进行加密
        user.setUserPwd(Md5Util.encode(newPassWord));
        // 4. 执行更新操作 受影响的行数小于1，更新失败
        AssertUtil.isTrue(userMapper.updateByPrimaryKeySelective(user) < 1, "密码更新失败！");

    }

    /**
     * @param []
     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     * @description 查询所有销售人员
     * @date 2021/1/15 13:39
     **/
    public List<Map<String, Object>> queryAllSales() {
        return userMapper.queryAllSales();
    }


    /**
     * @param [query] 用户多条件查询对象
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @description 多条件分页查询用户数据
     * @date 2021/1/17 09:06
     **/
    public Map<String, Object> queryUserByParams(UserQuery query) {
        PageHelper.startPage(query.getPage(), query.getLimit());
        PageInfo<User> userPageInfo = new PageInfo<>(userMapper.selectByParams(query));
        return QueryUtil.buildInfo(userPageInfo);
    }

    /**
     * @param [user]
     * @return void
     * @description 新增用户
     * @date 2021/1/17 09:20
     **/
    @Transactional(propagation = Propagation.REQUIRED)
    public void saveUser(User user) {
        // 1. 参数校验
        checkParams(user);
        // 2. 设置默认值
        setDefaultValue(user);
        // 3. 执行添加 判断结果
        AssertUtil.isTrue(userMapper.insertSelective(user) < 1, "用户添加失败！");

        // 4. 用户角色分配
        relationUserRole(user);
    }


    @Transactional
    public void updateUser(User user) {
        User temp = userMapper.selectByPrimaryKey(user.getId());
        AssertUtil.isTrue(null == temp, "待更新记录不存在！");
        checkParams(user);
        user.setUpdateDate(new Date());
        AssertUtil.isTrue(userMapper.updateByPrimaryKeySelective(user) < 1, "用户更新失败！");

        // 用户角色更新
        relationUserRole(user);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void deleteUserByIds(Integer[] ids) {
        AssertUtil.isTrue(null == ids || ids.length == 0, "请选择待删除的用户记录！");

        // 删除用户角色分配记录
        for (Integer id : ids) {
            // 查询用户分配的角色条数
            Integer count = userRoleMapper.countUserRoleByUserId(id);
            //删除用户角色分配记录
            if (count > 0) {
                AssertUtil.isTrue((userRoleMapper.deleteUserRoleByUserId(id) != count), "删除用户失败，请联系管理员！");
            }
        }

        AssertUtil.isTrue(deleteBatch(ids) != ids.length, "用户记录删除失败！");


    }

    private void setDefaultValue(User user) {
        user.setIsValid(1);
        user.setCreateDate(new Date());
        user.setUpdateDate(new Date());
        // 设置密码 加密
        user.setUserPwd(Md5Util.encode("123456"));
    }

    private void checkParams(User user) {
        AssertUtil.isTrue(StringUtils.isBlank(user.getUserName()), "用户名不能为空！");
        // 验证用户名是否存在
        User temp = userMapper.queryUserByName(user.getUserName());
        //  数据存在，且不是当前要修改的用户记录，则表示其他用户占用了该用户名
        AssertUtil.isTrue((null != temp && !(temp.getId().equals(user.getId()))), "该用户已存在！");
        AssertUtil.isTrue(StringUtils.isBlank(user.getEmail()), "请输入邮箱地址！");
        AssertUtil.isTrue(!PhoneUtil.isMobile(user.getPhone()), "手机号码格式不正确！");
    }


    /**
     * @param user            用户对象
     * @param newPassWord     新密码
     * @param oldPassWord     旧密码
     * @param confirmPassWord 确认密码
     * @return void
     * @description 验证修改密码参数
     * 用户ID：userId 非空 用户对象必须存在
     * 原始密码：oldPassword 非空 与数据库中密文密码保持一致
     * 新密码：newPassword 非空 与原始密码不能相同
     * 确认密码：confirmPassword 非空 与新密码保持一致
     * @date 2021/1/13 22:02
     **/
    private void checkUpdatePassWordParams(User user, String newPassWord, String oldPassWord, String confirmPassWord) {

        AssertUtil.isTrue(null == user, "用户未登录或不存在！");
        AssertUtil.isTrue(StringUtils.isBlank(newPassWord), "请输入新密码！");
        AssertUtil.isTrue(StringUtils.isBlank(oldPassWord), "请输入原始密码！");
        AssertUtil.isTrue(!(user.getUserPwd().equals(Md5Util.encode(oldPassWord))), "原始密码不正确！");
        AssertUtil.isTrue(oldPassWord.equals(newPassWord), "新密码不能与原始密码相同！");
        AssertUtil.isTrue(StringUtils.isBlank(confirmPassWord), "请输入确认密码！");
        AssertUtil.isTrue(!(newPassWord.equals(confirmPassWord)), "新密码与确认密码不一致！");
    }

    /**
     * @param user 用户记录
     * @return UserVo
     * @description 构建需要返回给前台的用户信息
     * @date 2021/1/13 16:34
     **/
    private UserVo buildUserInfo(User user) {
        UserVo userVo = new UserVo();
        //userVo.setUserId(user.getId());
        userVo.setUserIdStr(UserIDBase64.encoderUserID(user.getId())); //对用户ID进行加密
        userVo.setUserName(user.getUserName());
        userVo.setTrueName(user.getTrueName());
        return userVo;
    }

    /**
     * @param passWord 客户端传输的密码
     * @param userPwd  数据库用户密码
     * @return void
     * @description 密码校验
     * @date 2021/1/13 16:30
     **/
    private void checkPassWord(String passWord, String userPwd) {
        // 数据库中的密码是经过MD5加密的，因此需要讲客户端传输过来的密码先加密，再与数据库中的密码进行比对
        passWord = Md5Util.encode(passWord);

        AssertUtil.isTrue(!passWord.equals(userPwd), "密码不正确！");
    }

    /**
     * @param userName 用户名
     * @param passWord 密码
     * @return void
     * @description 参数校验
     * @date 2021/1/13 16:23
     **/
    private void checkLoginParams(String userName, String passWord) {
        AssertUtil.isTrue(StringUtils.isBlank(userName), "用户名不能为空！");
        AssertUtil.isTrue(StringUtils.isBlank(passWord), "密码不能为空！");
    }

    /**
     * @param [user]
     * @return void
     * @description 用户角色分配
     * @date 2021/1/23 14:54
     **/
    private void relationUserRole(User user){
        /**
         * 用户角色分配
         *   这里有个小技巧，如果用户原始角色存在 首先清空原始所有角色，添加新的用户角色到用户角色记录表
         */
        Integer userId = user.getId();
        String roleIds = user.getRoleIds();
        Integer count = userRoleMapper.countUserRoleByUserId(userId);
        if (count > 0) {
            AssertUtil.isTrue((userRoleMapper.deleteUserRoleByUserId(userId) != count), "用户角色分配失败！");
        }

        if (StringUtils.isNotBlank(roleIds)) {
            ArrayList<UserRole> userRoles = new ArrayList<>();
            String[] res = StringUtils.split(roleIds, ",");
            for (String s : res) {
                UserRole userRole = new UserRole();
                userRole.setUserId(userId);
                userRole.setRoleId(Integer.parseInt(s));
                userRole.setCreateDate(new Date());
                userRole.setUpdateDate(new Date());
                userRoles.add(userRole);
            }

            AssertUtil.isTrue((userRoleMapper.insertBatch(userRoles) != userRoles.size()), "用户角色分配失败，请联系管理员！");

        }

    }
}
